﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Linq;
using System.Web;
using System.Globalization;
using System.Threading.Tasks;

namespace BaseLib.Localiztion
{
    internal static class LocalizationEngine
    {
        private static string _resourcesPath;

        private static Dictionary<string, Dictionary<string, string>> _resources =
            new Dictionary<string, Dictionary<string, string>>();

        private static List<CultureInfo> _existingCultures = null;

        private static List<CultureInfo> ExistingCultures
        {
            get
            {
                if (_existingCultures == null)
                {
                    if (string.IsNullOrEmpty(_resourcesPath))
                        throw new DirectoryNotFoundException("Please call init before use.");

                    _existingCultures = new List<CultureInfo>();

                    DirectoryInfo dir = new DirectoryInfo(_resourcesPath);
                    foreach (var cultureFile in dir.GetFiles())
                    {
                        if (cultureFile.Extension == ".xml")
                            _existingCultures.Add(new CultureInfo(cultureFile.Name.Split('.')[0]));
                    }
                }

                return _existingCultures;
            }
        }

        internal static void Init(string resourcesPath)
        {
            _resources = new Dictionary<string, Dictionary<string, string>>();
            _resourcesPath = HttpContext.Current.Server.MapPath(resourcesPath) + "\\";

            Task.Factory.StartNew(() =>
            {
                foreach (var culture in ExistingCultures)
                {
                    EnsureCulture(culture.Name);
                }
            }
            );
        }

        internal static string GetResource(string key, string culture)
        {
            EnsureCulture(culture);

            if (!_resources[culture].ContainsKey(key))
                return "{" + key + "}";

            return _resources[culture][key];
        }

        private static bool EnsureCulture(string culture)
        {
            if (_resources.ContainsKey(culture))
                return true;

            string culturePath = _resourcesPath + "\\" + culture + ".xml";
            if (!File.Exists(culturePath))
                return false;

            XDocument cultureXml = XDocument.Parse(File.ReadAllText(culturePath));

            Dictionary<string, string> cultureDict = new Dictionary<string, string>();

            try
            {
                foreach (var item in cultureXml.Descendants("item"))
                {
                    cultureDict.Add(item.Attribute("key").Value, item.Value);
                }
            }
            catch
            {
                var duplicateKeys =
                    cultureXml.Descendants("item")
                        .GroupBy(x => x.Attribute("key").Value)
                        .Where(x => x.Count() > 1)
                        .Select(x => x.Key);
                if (duplicateKeys.Any())
                {
                    throw new Exception("The following keys are duplicates: " + string.Join(", ", duplicateKeys));
                }
                throw;
            }
            _resources.Add(culture, cultureDict);

            return true;
        }
    }
}
